package com.spring;

/**
 * @author 周宇
 * @create 2020-06-12 11:07
 * 通用二进制 十进制 十六进制
 */
public class GenericBinaryDecimalHex {
    public static void main(String[] args) {
        GenericBinaryDecimalHex genericBinaryDecimalHex = new GenericBinaryDecimalHex();
        genericBinaryDecimalHex.operator();
    }

    //任意进制到十进制之间的转换
    public void GenericDecimaShiftto() {
        /**
         * 进制转换：任意进制到十进制之间的转换
         * 前提：
         *     系数：每一个位置上的数字（110，个位系数就是0，十位系数是1...）
         *     基数：几进制的基数就是几（十进制的基数就是10...）
         *      权：从右往左,从0开始，对数字编号
         * 规律：
         *     任意进制到十进制转换都等于“这个数据的各位值*基数的权次次幂的和”
         * eg:
         *      十进制：157 = 7*10^0+5*10^1+1*10^2 = 7+50+100 = 157
         *      二进制：ob110 = 0*2^0+1*2^1+1*2^2 = 0+2+4 = 6
         *      八进制：0110 = 0*8^0+1*8^1+1*8^2 = 0+8+64 = 72
         *      十六进制：0xabc = c*16^0+b*16^1+a*16*2 = 12+176+2560 = 2748
         */
    }

    //十进制到任意进制之间的转换
    public void GenericDecimaRollout() {
        /**
         * 进制转换：十进制到任意进制之间的转换
         *      十进制转换为二进制，八进制，十六进制
         * 规律：
         *      除基数取余数，直到商为0，余数反转
         *      把十进制100转化为二进制，八进制，十六进制
         */
    }


    //位运算
    // 原码 反码 补码
    // 正数的原码反码补码都是本身  负数的原码、反码、补码各是不同的(负数是除符号为不变，其余按位求反，在末尾加1)
    public void bitoperation() {
        /**
         * 位运算符种类
         * &：按位 与    规则：两个同为1的时候才为1
         * I：按位 或    规则：两者只要一个为1name结果就为1
         * ^：按位 异或  规则：两者不同为时为1，相同为0
         * ~：按位 取反  规则：1->0  0->1
         */
        //按位 与 &
        // 3 & 4 结果是多少？
        // 在进行位运算的时候把数据转换为二进制！并且全部都是二进制的补码形式！
        // 3的二进制：  0b00000000000000000000000000000011
        // 4的二进制：  0b00000000000000000000000000000100
        // 3和4按位 与：0b00000000000000000000000000000000
        System.out.println("3 & 4=" + (3 & 4));

        //按位 或 |
        // 3 | 4 结果是多少？
        // 在进行位运算的时候把数据转换为二进制！并且全部都是二进制的补码形式！
        // 3的二进制：  0b00000000000000000000000000000011
        // 4的二进制：  0b00000000000000000000000000000100
        // 3和4按位 或：0b00000000000000000000000000000111
        System.out.println("3 | 4=" + (3 | 4));

        //按位 异或 ^
        // 3 ^ 4 结果是多少？
        // 在进行位运算的时候把数据转换为二进制！并且全部都是二进制的补码形式！
        // 3的二进制：    0b00000000000000000000000000000011
        // 4的二进制：    0b00000000000000000000000000000100
        // 3和4按位 异或： 0b00000000000000000000000000000111
        System.out.println("3 ^ 4=" + (3 ^ 4));

        //按位 取反 ~
        // 3 ^ 4 结果是多少？
        // 在进行位运算的时候把数据转换为二进制！并且全部都是二进制的补码形式！
        // 3的二进制：0b00000000000000000000000000000011
        // 3 取反：  0b11111111111111111111111111111100  结果错误×  java中使用补码计算 3的补码取反-4
        System.out.println("~3=" + ~3);

        /**
         * 3的二进制：0b00000000000000000000000000000011
         * 3 原码：  0b11111111111111111111111111111100
         * 3 反码：  0b11111111111111111111111111111100  (正数本身)
         * 3 补码：  0b11111111111111111111111111111100  (正数本身)负数
         * 已知补码求反码
         * -1
         * ---------------------------------------------
         *           0b11111111111111111111111111111011
         * 取反
         * ---------------------------------------------
         *           0b10000000000000000000000000000100  =-4
         */
        System.out.println(~3);
    }

    //加密
    public void encrypt() {
        /**
         * 一个数据对相同的数据异或两次其值不变
         * eg:
         *      数据a  数据b  a^b^b=a
         */
        int a = 3;
        int b = 4;
        System.out.println("a^b=" + (a ^ b));
        System.out.println("a^b^b=" + (a ^ b ^ b));
    }

    /**
     * 变量交换
     */
    public void variableExchange() {
        int i = 10;
        int j = 20;
        System.out.println("交换前：i=" + i + "\tj=" + j);
        //方法1：定义一个中间变量
        int c;
        c = i;
        i = j;
        j = c;
        System.out.println("方法1 使用中间量：i=" + i + "\tj=" + j);

        //不允许使用中间量
        //可以* / 实现
        i = i + j;
        j = i - j;
        i = i - j;
        System.out.println("方法2 通过运算巧妙转换：i=" + i + "\tj=" + j);

        //效率最好 装逼常用 通过位运算
        i = i ^ j;
        j = i ^ j;  //相当于j=i^j^j=i
        i = i ^ j;  //相当于i=j^i^i=j
        System.out.println("方法2 通过位运算巧妙转换：i=" + i + "\tj=" + j);
    }


    public void operator() {
        /**
         * << 左移：让操作数乘以2的n次幂 n就是移动的位数
         * << 右移：让操作数除以2的n次幂 n就是移动的位数
         */
        System.out.println("3 << 2 = " + (3 << 2));//3*2^2=12
        System.out.println("32 >> 2 = " + (32 >> 2));//3/2^2=0.75

        //无符号右移
        //-32
        //源码:    10000000000000000000000000100000
        //反码:    11111111111111111111111111011111
        //补码:    11111111111111111111111111100000
        //右移两位: 11111111111111111111111111111000  //也是补码,右边删除两位，左边根据符号位补两个1
        //根据补码求源码显示
        // -1 得到反码
        //      : 11111111111111111111111111110111
        // 取反 得到源码
        //      : 10000000000000000000000000001000
    }
}
